//
//  MMWDHEnDe.h
//  MMWPT
//
//  Created by 高得华 on 2018/10/11.
//  Copyright © 2018年 高得华. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <Security/Security.h>

/// 默认使用kCCOptionPKCS7Padding填充
#define kPaddingMode kCCOptionPKCS7Padding


//MARK: - ===== 加密解密管理类 ===== -
NS_ASSUME_NONNULL_BEGIN

@interface MMWDHEnDe : NSObject

///添加私密
+ (SecKeyRef)addPrivateKey:(NSString *)key;
///加密  START: Encryption & Decryption with RSA private key
+ (NSData *)encryptData:(NSData *)data withKeyRef:(SecKeyRef)keyRef;
///解密
+ (NSData *)decryptData:(NSData *)data withKeyRef:(SecKeyRef)keyRef;

@end

NS_ASSUME_NONNULL_END


///NSData
@interface NSData (MMWDHEnDeBase64)

//MARK: - ====== Base64 ====== -
+ (NSData *_Nullable)dataWithBase64EncodedStr:(NSString *_Nullable)string;
- (NSString *_Nullable)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth;
- (NSString *_Nullable)base64EncodedString;

//MARK: - ====== RSA ===== -
///RSA加密 公密 return raw data
+ (NSData *_Nullable)encryptData:(NSData *_Nullable)data publicKey:(NSString *_Nullable)pubKey;
///RSA解密 公密 return raw data
+ (NSData *_Nullable)decryptData:(NSData *_Nullable)data publicKey:(NSString *_Nullable)pubKey;
///RSA解密 私密 return raw data
+ (NSData *_Nullable)decryptData:(NSData *_Nullable)data privateKey:(NSString *_Nullable)privKey;
///将图片压缩至 指定的 大小
+ (NSData *_Nullable)imageData:(UIImage *)image;
///将图片压缩至 指定的 大小
//+ (NSData *_Nullable)dataCompress:(NSData *)data;

@end

///字符串
@interface NSString (MMWDHEnDeBase64)

///随机生成一个 指定长度的字符串
+ (NSString *)randomStringWithLength:(NSInteger)len;
///指定一个字符串 随机生成一个 指定长度的新字符串
- (NSString *)randomStrWithLength:(NSInteger)len;

//MARK: - ====== Base64 ====== -
+ (NSString *_Nullable)stringWithBase64EncodedString:(NSString *_Nullable)string;
- (NSString *_Nullable)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth;
- (NSString *_Nullable)base64EncodedString;
- (NSString *_Nullable)base64DecodedString;
- (NSData *_Nullable)base64DecodedData;

//MARK: - ====== RSA ===== -
///RSA加密 公密 return base64 encoded string
+ (NSString *_Nullable)encryptString:(NSString *_Nullable)str publicKey:(NSString *_Nullable)pubKey;
///RSA解密 公密 decrypt base64 encoded string, convert result to string(not base64 encoded)
+ (NSString *_Nullable)decryptString:(NSString *_Nullable)str publicKey:(NSString *_Nullable)pubKey;
///RSA解密 私密 decrypt base64 encoded string, convert result to string(not base64 encoded)
+ (NSString *_Nullable)decryptString:(NSString *_Nullable)str privateKey:(NSString *_Nullable)privKey;


/// 消除收尾空格
- (NSString *)sb_removeBothEndsWhitespace;
/// 消除收尾空格+换行符
- (NSString *)sb_removeBothEndsWhitespaceAndNewline;
// 消除收尾空格
- (NSString *)sb_trimWhitespace;
/// 编码
- (NSString *)sb_URLEncoding;
// 消除所有空格
- (NSString *)sb_trimAllWhitespace;



// 自定义正数格式(金额的格式转化) 94,862.57
+ (NSString *)stringChangeMoneyWithDouble:(double)number;

// 金额的格式转化 ￥94,862.57这样的形式
- (NSString *)stringChangeMoney;

/**
 * 金额的格式转化
 * str : 金额的字符串
 * numberStyle : 金额转换的格式
 * return  NSString : 转化后的金额格式字符串
 */
- (NSString *)stringChangeMoneyNumberStyle:(NSNumberFormatterStyle)numberStyle;


// 16进制转NSData
- (NSData *)convertHexStrToData;

@end


//MARK: - ====== 哈希算法 Hash ====== -
@interface NSString (MMWDHEnDeHash)

/// 返回结果：32长度(128位，16字节，16进制字符输出则为32字节长度)   终端命令：md5 -s "123"
- (NSString *_Nullable)md5Hash;

/// 返回结果：40长度   终端命令：echo -n "123" | openssl sha -sha1
- (NSString *_Nullable)sha1Hash;

/// 返回结果：56长度   终端命令：echo -n "123" | openssl sha -sha224
- (NSString *_Nullable)sha224Hash;

/// 返回结果：64长度   终端命令：echo -n "123" | openssl sha -sha256
- (NSString *_Nullable)sha256Hash;

/// 返回结果：96长度   终端命令：echo -n "123" | openssl sha -sha384
- (NSString *_Nullable)sha384Hash;

/// 返回结果：128长度   终端命令：echo -n "123" | openssl sha -sha512
- (NSString *_Nullable)sha512Hash;

#pragma mark - HMAC

/// 返回结果：32长度  终端命令：echo -n "123" | openssl dgst -md5 -hmac "123"
- (NSString *_Nullable)hmacMD5WithKey:(NSString *_Nullable)key;

/// 返回结果：40长度   echo -n "123" | openssl sha -sha1 -hmac "123"
- (NSString *_Nullable)hmacSHA1WithKey:(NSString *_Nullable)key;
- (NSString *_Nullable)hmacSHA224WithKey:(NSString *_Nullable)key;
- (NSString *_Nullable)hmacSHA256WithKey:(NSString *_Nullable)key;
- (NSString *_Nullable)hmacSHA384WithKey:(NSString *_Nullable)key;
- (NSString *_Nullable)hmacSHA512WithKey:(NSString *_Nullable)key;

@end




//MARK: - ====== AES、DES(加密/解密) ====== -
@interface NSString (MMWDHEnDeADES)

#pragma mark - AES加密

/**
 AES-CBC模式加密，默认模式
 @param key Hex形式，密钥支持128 192 256bit，16、24、32字节，转换为16进制字符串长度为32、48、64，长度错误将抛出异常
 @param iv 进制字符串形式；初始化向量iv为16字节。如果为nil，则初始化向量为0
 @return 加密结果为base64编码
 */
- (NSString *_Nullable)aesEncryptWithHexKey:(NSString *_Nullable)key hexIv:(NSString *_Nullable)iv;

/**
 AES-CBC模式加密，默认模式
 @param key 密钥支持128 192 256bit，16、24、32字节，长度错误将抛出异常
 @param iv 进制字符串形式；初始化向量iv为16字节。如果为nil，则初始化向量为0
 @return 加密结果为base64编码
 */
- (NSString *_Nullable)aesEncryptWithKey:(NSString *_Nullable)key iv:(NSString *_Nullable)iv;

/**
 AES-CBC模式加密，默认模式 要加密的数据
 @param key 密钥支持128 192 256bit，16、24、32字节，长度错误将抛出异常
 @param iv 初始化向量iv为16字节。如果为nil，则初始化向量为0
 @return 加密结果为NSData形式
 */
- (NSData *_Nullable)aesEncryptWithDataKey:(NSData *_Nullable)key dataIv:(NSData *_Nullable)iv;

/**
 AES-ECB模式加密
 @param key Hex形式，密钥支持128 192 256bit，16、24、32字节，转换为16进制字符串长度为32、48、64，长度错误将抛出异常
 @return 加密结果为base64编码
 */
- (NSString *_Nullable)aesECBEncryptWithHexKey:(NSString *_Nullable)key;

/**
 AES-ECB模式加密
 @param key base64形式，密钥支持128 192 256bit，16、24、32字节，转换为16进制字符串长度为32、48、64，长度错误将抛出异常
 @return 加密结果为base64编码
 */
- (NSString *_Nullable)aesECBEncryptWithBase64Key:(NSString *_Nullable)key;

/**
 AES-ECB模式加密
 @param key 字符串形式，密钥支持128 192 256bit，16、24、32字节，长度错误将抛出异常
 @return 加密结果为base64编码
 */
- (NSString *_Nullable)aesECBEncryptWithKey:(NSString *_Nullable)key;

/**
 AES-ECB模式加密
 @param key 密钥支持128 192 256bit，16、24、32字节，长度错误将抛出异常
 */
- (NSData *_Nullable)aesECBEncryptWithDataKey:(NSData *_Nullable)key;

#pragma mark - AES解密

/**
 AES-CBC模式解密，要求NSString为base64的结果
 @param key 密钥支持128 192 256bit，16、24、32字节，长度错误将抛出异常
 @param iv 进制字符串形式；初始化向量iv为16字节。如果为nil，则初始化向量为0
 */
- (NSString *_Nullable)aesBase64StringDecryptWithHexKey:(NSString *_Nullable)key hexIv:(NSString *_Nullable)iv;

/**
 AES-CBC模式解密
 @param key 密钥支持128 192 256bit，16、24、32字节，长度错误将抛出异常
 @param iv 初始化向量iv为16字节。如果为nil，则初始化向量为0
 */
+ (NSData *_Nullable)aesDecryptWithData:(NSData *_Nullable)data dataKey:(NSData *_Nullable)key dataIv:(NSData *_Nullable)iv;

///ECB模式解密，要求输入为Base64格式的nsstring，返回为NSString
- (NSString *_Nullable)aesECBBase64StringDecryptWithHexKey:(NSString *_Nullable)key;

///ECB模式解密，要求输入为Base64格式，返回为NSString
- (NSString *_Nullable)aesECBBase64StringDecryptWithBase64Key:(NSString *_Nullable)key;

///ECB模式解密，返回为NSData
+ (NSData *_Nullable)aesECBDecryptWithData:(NSData *_Nullable)data withDataKey:(NSData *_Nullable)key;


///*
// ECB模式解密，返回base64编码
// */
//- (NSString *)aesECBDecryptWithHexKey:(NSString *)key;
//
///*
// ECB模式解密，返回NSData
// */
//- (NSData *)aesECBDecryptWithDataKey:(NSData *)key;

#pragma mark - DES加密
///DES加密 key为NSString形式 结果返回base64编码
- (NSString *_Nullable)desEncryptWithKey:(NSString *_Nullable)key;
///DES加密 key为NSData形式 结果返回NSData
- (NSData *_Nullable)desEncryptWithDataKey:(NSData *_Nullable)key;

#pragma mark - DES解密
///DES解密，字符串必须为base64格式，key为字符串形式
- (NSString *_Nullable)desDecryptWithKey:(NSString *_Nullable)key;
///DES解密
+ (NSData *_Nullable)desDecryptWithData:(NSData *_Nullable)data dataKey:(NSData *_Nullable)key;

@end





//MARK: - ====== CocoaSecurity ===== -
#pragma mark - CocoaSecurityResult
@interface CocoaSecurityResult : NSObject

@property (strong, nonatomic, readonly) NSData * _Nullable data;
@property (strong, nonatomic, readonly) NSString * _Nullable utf8String;
@property (strong, nonatomic, readonly) NSString * _Nullable hex;
@property (strong, nonatomic, readonly) NSString * _Nullable hexLower;
@property (strong, nonatomic, readonly) NSString * _Nullable base64;

- (id _Nullable )initWithBytes:(unsigned char[_Nullable])initData length:(NSUInteger)length;

@end


#pragma mark - CocoaSecurity
@interface CocoaSecurity : NSObject
#pragma mark - AES Encrypt
+ (CocoaSecurityResult *_Nullable)aesEncrypt:(NSString *_Nullable)data key:(NSString *_Nullable)key;
+ (CocoaSecurityResult *_Nullable)aesEncrypt:(NSString *_Nullable)data hexKey:(NSString *_Nullable)key hexIv:(NSString *_Nullable)iv;
+ (CocoaSecurityResult *_Nullable)aesEncrypt:(NSString *_Nullable)data key:(NSData *_Nullable)key iv:(NSData *_Nullable)iv;
+ (CocoaSecurityResult *_Nullable)aesEncryptWithData:(NSData *_Nullable)data key:(NSData *_Nullable)key iv:(NSData *_Nullable)iv;
#pragma mark AES Decrypt
+ (CocoaSecurityResult *_Nullable)aesDecryptWithBase64:(NSString *_Nullable)data key:(NSString *_Nullable)key;
+ (CocoaSecurityResult *_Nullable)aesDecryptWithBase64:(NSString *_Nullable)data hexKey:(NSString *_Nullable)key hexIv:(NSString *_Nullable)iv;
+ (CocoaSecurityResult *_Nullable)aesDecryptWithBase64:(NSString *_Nullable)data key:(NSData *_Nullable)key iv:(NSData *_Nullable)iv;
+ (CocoaSecurityResult *_Nullable)aesDecryptWithData:(NSData *_Nullable)data key:(NSData *_Nullable)key iv:(NSData *_Nullable)iv;

#pragma mark - MD5
+ (CocoaSecurityResult *_Nullable)md5:(NSString *_Nullable)hashString;
+ (CocoaSecurityResult *_Nullable)md5WithData:(NSData *_Nullable)hashData;
#pragma mark HMAC-MD5
+ (CocoaSecurityResult *_Nullable)hmacMd5:(NSString *_Nullable)hashString hmacKey:(NSString *_Nullable)key;
+ (CocoaSecurityResult *_Nullable)hmacMd5WithData:(NSData *_Nullable)hashData hmacKey:(NSString *_Nullable)key;

#pragma mark - SHA
+ (CocoaSecurityResult *_Nullable)sha1:(NSString *_Nullable)hashString;
+ (CocoaSecurityResult *_Nullable)sha1WithData:(NSData *_Nullable)hashData;
+ (CocoaSecurityResult *_Nullable)sha224:(NSString *_Nullable)hashString;
+ (CocoaSecurityResult *_Nullable)sha224WithData:(NSData *_Nullable)hashData;
+ (CocoaSecurityResult *_Nullable)sha256:(NSString *_Nullable)hashString;
+ (CocoaSecurityResult *_Nullable)sha256WithData:(NSData *_Nullable)hashData;
+ (CocoaSecurityResult *_Nullable)sha384:(NSString *_Nullable)hashString;
+ (CocoaSecurityResult *_Nullable)sha384WithData:(NSData *_Nullable)hashData;
+ (CocoaSecurityResult *_Nullable)sha512:(NSString *_Nullable)hashString;
+ (CocoaSecurityResult *_Nullable)sha512WithData:(NSData *_Nullable)hashData;
#pragma mark HMAC-SHA
+ (CocoaSecurityResult *_Nullable)hmacSha1:(NSString *_Nullable)hashString hmacKey:(NSString *_Nullable)key;
+ (CocoaSecurityResult *_Nullable)hmacSha1WithData:(NSData *_Nullable)hashData hmacKey:(NSString *_Nullable)key;
+ (CocoaSecurityResult *_Nullable)hmacSha224:(NSString *_Nullable)hashString hmacKey:(NSString *_Nullable)key;
+ (CocoaSecurityResult *_Nullable)hmacSha224WithData:(NSData *_Nullable)hashData hmacKey:(NSString *_Nullable)key;
+ (CocoaSecurityResult *_Nullable)hmacSha256:(NSString *_Nullable)hashString hmacKey:(NSString *_Nullable)key;
+ (CocoaSecurityResult *_Nullable)hmacSha256WithData:(NSData *_Nullable)hashData hmacKey:(NSString *_Nullable)key;
+ (CocoaSecurityResult *_Nullable)hmacSha384:(NSString *_Nullable)hashString hmacKey:(NSString *_Nullable)key;
+ (CocoaSecurityResult *_Nullable)hmacSha384WithData:(NSData *_Nullable)hashData hmacKey:(NSString *_Nullable)key;
+ (CocoaSecurityResult *_Nullable)hmacSha512:(NSString *_Nullable)hashString hmacKey:(NSString *_Nullable)key;
+ (CocoaSecurityResult *_Nullable)hmacSha512WithData:(NSData *_Nullable)hashData hmacKey:(NSString *_Nullable)key;
@end


#pragma mark - CocoaSecurityEncoder
@interface CocoaSecurityEncoder : NSObject
- (NSString *_Nullable)base64:(NSData *_Nullable)data;
- (NSString *_Nullable)hex:(NSData *_Nullable)data useLower:(BOOL)isOutputLower;
@end


#pragma mark - CocoaSecurityDecoder
@interface CocoaSecurityDecoder : NSObject
- (NSData *_Nullable)base64:(NSString *_Nullable)data;
- (NSData *_Nullable)hex:(NSString *_Nullable)data;
@end




